/* ==============================================================================
*
*   Copyright (c) 2010, Pierre Favier
*   All rights reserved.
*
*   NTasking is free software: you can redistribute it and/or modify it
*   under the terms of the GNU General Public License as published by the
*   Free Software Foundation.
*
*   Redistribution and use in source and binary forms, with or without
*   modification, are permitted provided that the following conditions
*   are met:
*
*   -   Redistributions of source code must retain the above copyright notice,
*       this list of conditions and the following disclaimer.
*
*   -   Redistributions in binary form must reproduce the above
*       copyright notice, this list of conditions and the following
*       disclaimer in the documentation and/or other materials
*       provided with the distribution.
*
*   THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
*   WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
*   OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
*   DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
*   BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
*   EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
*   TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
*   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
*   ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
*   TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
*   THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
*   SUCH DAMAGE.
*
* ============================================================================== */

using System;
using System.Collections.Generic;
using NUnit.Framework;
using Rhino.Mocks;
using Rhino.Mocks.Constraints;

namespace NTasking.ValidationTests.Other
{

    [TestFixture]
    public class ProtectedDeclaration : ValidationTest
    {

        internal class AProtected : ValidationTestProtected
        {

            [Entry]
            internal Action Put0 { get; private set; }
            [Entry]
            internal Action<int> Put1 { get; private set; }
            [Entry]
            internal Action<int, int> Put2 { get; private set; }
            [Entry]
            internal Action<int, int, int> Put3 { get; private set; }
            [Entry]
            internal Action<int, int, int, int> Put4 { get; private set; }

            [Entry]
            internal Func<bool> Get0 { get; private set; }
            [Entry]
            internal Func<int, bool> Get1 { get; private set; }
            [Entry]
            internal Func<int, int, bool> Get2 { get; private set; }
            [Entry]
            internal Func<int, int, int, bool> Get3 { get; private set; }
            [Entry]
            internal Func<int, int, int, int, bool> Get4 { get; private set; }

            [Entry]
            internal ActionFamily<double> FPut0 { get; private set; }
            [Entry]
            internal ActionFamily<double, int> FPut1 { get; private set; }
            [Entry]
            internal ActionFamily<double, int, int> FPut2 { get; private set; }
            [Entry]
            internal ActionFamily<double, int, int, int> FPut3 { get; private set; }
            [Entry]
            internal ActionFamily<double, int, int, int, int> FPut4 { get; private set; }

            [Entry]
            internal FuncFamily<double, bool> FGet0 { get; private set; }
            [Entry]
            internal FuncFamily<double, int, bool> FGet1 { get; private set; }
            [Entry]
            internal FuncFamily<double, int, int, bool> FGet2 { get; private set; }
            [Entry]
            internal FuncFamily<double, int, int, int, bool> FGet3 { get; private set; }
            [Entry]
            internal FuncFamily<double, int, int, int, int, bool> FGet4 { get; private set; }


            [ReadOnlyOperation]
            internal Func<bool> ROGet0 { get; private set; }
            [ReadOnlyOperation]
            internal Func<int, bool> ROGet1 { get; private set; }
            [ReadOnlyOperation]
            internal Func<int, int, bool> ROGet2 { get; private set; }
            [ReadOnlyOperation]
            internal Func<int, int, int, bool> ROGet3 { get; private set; }
            [ReadOnlyOperation]
            internal Func<int, int, int, int, bool> ROGet4 { get; private set; }


            [ReadWriteOperation]
            internal Action RWPut0 { get; private set; }
            [ReadWriteOperation]
            internal Action<int> RWPut1 { get; private set; }
            [ReadWriteOperation]
            internal Action<int, int> RWPut2 { get; private set; }
            [ReadWriteOperation]
            internal Action<int, int, int> RWPut3 { get; private set; }
            [ReadWriteOperation]
            internal Action<int, int, int, int> RWPut4 { get; private set; }

            [ReadWriteOperation]
            internal Func<bool> RWGet0 { get; private set; }
            [ReadWriteOperation]
            internal Func<int, bool> RWGet1 { get; private set; }
            [ReadWriteOperation]
            internal Func<int, int, bool> RWGet2 { get; private set; }
            [ReadWriteOperation]
            internal Func<int, int, int, bool> RWGet3 { get; private set; }
            [ReadWriteOperation]
            internal Func<int, int, int, int, bool> RWGet4 { get; private set; }


            public AProtected(IValidationTestResult result) : base(result)
            {
                Entry(Put0, () => true, () => { });
                Entry(Put1, () => true, (p1) => { });
                Entry(Put2, () => true, (p1, p2) => { });
                Entry(Put3, () => true, (p1, p2, p3) => { });
                Entry(Put4, () => true, (p1, p2, p3, p4) => { });

                Entry(Get0, () => true, () => { return true; });
                Entry(Get1, () => true, (p1) => { return true; });
                Entry(Get2, () => true, (p1, p2) => { return true; });
                Entry(Get3, () => true, (p1, p2, p3) => { return true; });
                Entry(Get4, () => true, (p1, p2, p3, p4) => { return true; });

                Entry(FPut0, (i) => true, (i) => { });
                Entry(FPut1, (i) => true, (i, p1) => { });
                Entry(FPut2, (i) => true, (i, p1, p2) => { });
                Entry(FPut3, (i) => true, (i, p1, p2, p3) => { });
                Entry(FPut4, (i) => true, (i, p1, p2, p3, p4) => { });

                Entry(FGet0, (i) => true, (i) => { return true; });
                Entry(FGet1, (i) => true, (i, p1) => { return true; });
                Entry(FGet2, (i) => true, (i, p1, p2) => { return true; });
                Entry(FGet3, (i) => true, (i, p1, p2, p3) => { return true; });
                Entry(FGet4, (i) => true, (i, p1, p2, p3, p4) => { return true; });

                ReadWriteOperation(RWPut0, () => { });
                ReadWriteOperation(RWPut1, (p1) => { });
                ReadWriteOperation(RWPut2, (p1, p2) => { });
                ReadWriteOperation(RWPut3, (p1, p2, p3) => { });
                ReadWriteOperation(RWPut4, (p1, p2, p3, p4) => { });

                ReadWriteOperation(RWGet0, () => { return true; });
                ReadWriteOperation(RWGet1, (p1) => { return true; });
                ReadWriteOperation(RWGet2, (p1, p2) => { return true; });
                ReadWriteOperation(RWGet3, (p1, p2, p3) => { return true; });
                ReadWriteOperation(RWGet4, (p1, p2, p3, p4) => { return true; });

                ReadOnlyOperation(ROGet0, () => { return true; });
                ReadOnlyOperation(ROGet1, (p1) => { return true; });
                ReadOnlyOperation(ROGet2, (p1, p2) => { return true; });
                ReadOnlyOperation(ROGet3, (p1, p2, p3) => { return true; });
                ReadOnlyOperation(ROGet4, (p1, p2, p3, p4) => { return true; });
            }

        }


        [Test]
        public void TaskDeclaration()
        {
            AProtected prot = null;
            IValidationTestResult result = Mocks.DynamicMock<IValidationTestResult>();

            Ada.Declare(() =>
            {
                prot = new AProtected(result);

                // Setup text expectations

                Expect.Call(result.TestFailed).Repeat.Never();

                Mocks.ReplayAll();
            },
            Begin: () =>
            {
                // Start test execution

            });
        }

    }

}
